#include "picture.h"
#include "screenshotwindow.h"

#include <QPen>
#include <QDebug>

const int pictureFrameWidth = 3;

PicturePrivate::PicturePrivate()
{

}

Picture::Picture(QObject *parent)
    : QObject(parent)
    , d_ptr(new PicturePrivate)
{
    init();
}

QRect Picture::rect() const
{
    if (d_ptr)
    {
        return d_ptr->m_Rect;
    }

    return QRect();
}

void Picture::setRect(QRect rect)
{
    if (rect.width() <=3 || rect.height() <= 3)
    {
        return;
    }
    if (d_ptr)
    {
        d_ptr->m_Rect = rect;
        updateHandle();

    }
}

void Picture::setRect(const QPoint &topLeft, const QSize &size)
{
    setRect(QRect(topLeft, size));
}

void Picture::setSize(const QSize &size)
{
    if (d_ptr)
    {
        d_ptr->m_Rect.setSize(size);
        updateHandle();
    }
}

void Picture::paint(QPainter *painter)
{
    if (painter && d_ptr)
    {
        if (d_ptr->m_Rect.size().width() >= 2 && d_ptr->m_Rect.size().height() >= 2)
        {
            painter->save();
            QPen painterPen = painter->pen();
            painterPen.setWidth(pictureFrameWidth);
            painterPen.setColor(QColor(Qt::blue));
            painter->setPen(painterPen);
            painter->drawRect(adjusted());
            painter->restore();
            QList<SizeHandle>::iterator iter = d_ptr->m_sizeHandleList.begin();
            for (; d_ptr->m_sizeHandleList.end() != iter; ++iter)
            {
                (*iter).paint(painter);
            }
        }
    }
}

uint Picture::frameWidth() const
{
    return pictureFrameWidth;
}

void Picture::updateHandle()
{
    if (d_ptr)
    {
        QList<SizeHandle>::iterator iter = d_ptr->m_sizeHandleList.begin();
        for (; d_ptr->m_sizeHandleList.end() != iter; ++iter)
        {
            switch((*iter).direction())
            {
            case SizeHandle::Handle_None:
                break;
            case SizeHandle::LeftTop:
                (*iter).setCenter(topLeft());
                break;
            case SizeHandle::Top:
                (*iter).setCenter(topCenter());
                break;
            case SizeHandle::RightTop:
                (*iter).setCenter(topRight());
                break;
            case SizeHandle::Right:
                (*iter).setCenter(rightCenter());
                break;
            case SizeHandle::RightBottom:
                (*iter).setCenter(bottomRight());
                break;
            case SizeHandle::Bottom:
                (*iter).setCenter(bottomCenter());
                break;
            case SizeHandle::LeftBottom:
                (*iter).setCenter(bottomLeft());
                break;
            case SizeHandle::Left:
                (*iter).setCenter(leftCenter());
                break;
            }
        }
    }
}

QRect Picture::adjusted() const
{
    QRect rect;
    if (d_ptr)
    {
        rect = d_ptr->m_Rect.adjusted(-pictureFrameWidth/2, -pictureFrameWidth/2, pictureFrameWidth/2, pictureFrameWidth/2);
    }
    return rect;
}

QPoint Picture::move(const QPoint &pt)
{
    QPoint topLeft(d_ptr->m_moveRect.topLeft());
    if (d_ptr)
    {
        QPoint parentTopLeft(0, 0);
        QPoint parentBottomRight(d_ptr->m_parentRect.width(), d_ptr->m_parentRect.height());
        topLeft = (topLeft + pt);
        QPoint bottomRight = (d_ptr->m_moveRect.bottomRight() + pt);
        if (topLeft.x() < parentTopLeft.x())
        {
            topLeft.setX(parentTopLeft.x());
        }
        if (topLeft.y() < parentTopLeft.y())
        {
            topLeft.setY(parentTopLeft.y());
        }
        if (bottomRight.x() > parentBottomRight.x())
        {
            topLeft.setX(parentBottomRight.x()-d_ptr->m_Rect.width());
        }
        if (bottomRight.y() > parentBottomRight.y())
        {
            topLeft.setY(parentBottomRight.y()-d_ptr->m_Rect.height());
        }
        QRect rect(topLeft, d_ptr->m_Rect.size());
//        d_ptr->m_Rect.setTopLeft(topLeft);
        setRect(rect);
        updateHandle();
    }

    return topLeft;
}

QPoint Picture::resize(int dir, const QPoint &pt)
{
    if (!d_ptr)
    {
        return QPoint();
    }
    QRect rectTmp;
    switch (dir) {
    case SizeHandle::LeftTop:
        rectTmp = rect();
        rectTmp.setTopLeft(d_ptr->m_moveRect.topLeft() + pt);
        setRect(rectTmp);
        break;
    case SizeHandle::Top:
        rectTmp = rect();
        rectTmp.setTop(d_ptr->m_moveRect.top() + pt.y());
        setRect(rectTmp);
        break;
    case SizeHandle::RightTop:
        rectTmp = rect();
        rectTmp.setTopRight(d_ptr->m_moveRect.topRight() + pt);
        setRect(rectTmp);
        break;
    case SizeHandle::Right:
        rectTmp = rect();
        rectTmp.setRight(d_ptr->m_moveRect.right() + pt.x());
        setRect(rectTmp);
        break;
    case SizeHandle::RightBottom:
        rectTmp = rect();
        rectTmp.setBottomRight(d_ptr->m_moveRect.bottomRight() + pt);
        setRect(rectTmp);
        break;
    case SizeHandle::Bottom:
        rectTmp = rect();
        rectTmp.setBottom(d_ptr->m_moveRect.bottom() + pt.y());
        setRect(rectTmp);
        break;
    case SizeHandle::LeftBottom:
        rectTmp = rect();
        rectTmp.setBottomLeft(d_ptr->m_moveRect.bottomLeft() + pt);
        setRect(rectTmp);
        break;
    case SizeHandle::Left:
        rectTmp = rect();
        rectTmp.setLeft(d_ptr->m_moveRect.left() + pt.x());
        setRect(rectTmp);
        break;
    }

    return d_ptr->m_Rect.topLeft();
}

QPoint Picture::topLeft() const
{
    return adjusted().topLeft();
}

QPoint Picture::topCenter() const
{
    QRect rect(adjusted());
    return QPoint(rect.left()+rect.width()/2, rect.top());
}

QPoint Picture::topRight() const
{
    QRect rect(adjusted());

    return QPoint(rect.left()+rect.width(), rect.top());;
}

QPoint Picture::rightCenter() const
{
    QRect rect(adjusted());

    return QPoint(rect.right(), rect.top()+rect.height()/2);
}

QPoint Picture::bottomRight() const
{
    QRect rect(adjusted());

    return QPoint(rect.right(), rect.top()+rect.height());
}

QPoint Picture::bottomCenter() const
{
    QRect rect(adjusted());

    return QPoint(rect.left()+rect.width()/2, rect.bottom());
}

QPoint Picture::bottomLeft() const
{
    QRect rect(adjusted());

    return QPoint(rect.left(), rect.bottom());
}

QPoint Picture::leftCenter() const
{
    QRect rect(adjusted());

    return QPoint(rect.left(), rect.top()+rect.height()/2);
}

int Picture::detectCursor(const QPoint &pt, int &dir) const
{
    //判断是否在锚点的范围内
    int cursor = ScreenshotWindow::None;
    dir = inDirectionSize(pt);
    if (dir > 0)
    {
        cursor = ScreenshotWindow::Size;
        d_ptr->m_moveRect = d_ptr->m_Rect;
    }
    else
    {
        if (d_ptr)
        {
            if (d_ptr->m_Rect.contains(pt))
            {
                cursor = ScreenshotWindow::Move;
                d_ptr->m_moveRect = d_ptr->m_Rect;
            }
        }
    }

    return cursor;
}

int Picture::inDirectionSize(const QPoint &pt) const
{
    if (!d_ptr->m_Rect.size().width() && !d_ptr->m_Rect.size().height())
    {
        return 0;
    }
    if (d_ptr)
    {
        QList<SizeHandle>::const_iterator iter = d_ptr->m_sizeHandleList.begin();
        for (; d_ptr->m_sizeHandleList.end() != iter; ++iter)
        {
            if ((*iter).containsPoint(pt))
            {
                return (*iter).direction();
            }
        }
    }

    return 0;
}

void Picture::init()
{
    if (d_ptr)
    {
        for (int i=SizeHandle::LeftTop; i<=SizeHandle::Left; ++i)
        {
            SizeHandle handle;
            switch(i)
            {
            case SizeHandle::Handle_None:
                handle.setDirection(SizeHandle::Handle_None);
                break;
            case SizeHandle::LeftTop:
                handle.setDirection(SizeHandle::LeftTop);
                handle.setCenter(topLeft());
                break;
            case SizeHandle::Top:
                handle.setDirection(SizeHandle::Top);
                handle.setCenter(topCenter());
                break;
            case SizeHandle::RightTop:
                handle.setDirection(SizeHandle::RightTop);
                handle.setCenter(topRight());
                break;
            case SizeHandle::Right:
                handle.setDirection(SizeHandle::Right);
                handle.setCenter(rightCenter());
                break;
            case SizeHandle::RightBottom:
                handle.setDirection(SizeHandle::RightBottom);
                handle.setCenter(bottomRight());
                break;
            case SizeHandle::Bottom:
                handle.setDirection(SizeHandle::Bottom);
                handle.setCenter(bottomCenter());
                break;
            case SizeHandle::LeftBottom:
                handle.setDirection(SizeHandle::LeftBottom);
                handle.setCenter(bottomLeft());
                break;
            case SizeHandle::Left:
                handle.setDirection(SizeHandle::Left);
                handle.setCenter(leftCenter());
                break;
            }
            d_ptr->m_sizeHandleList.append(handle);
        }
    }
}
